﻿#include "ui/tabctrl.h"
#include "ui/panel.h"
#include "ui/button.h"
#include "context.h"
#include "draw.h"

using namespace std;
using namespace anip;

class ui::TabControl::HeaderButton : public ui::ButtonBase
{
protected:
	int getTextWidth() override
	{
		return INT_MAX;
	}

public:
	Page* page;

	HeaderButton(ui::Container* parent, ui::TabControl::Page& pg) :
		ButtonBase(parent), page(&pg)
	{
		pg._btn = this;
		layoutOptions.type = ui::Control::LayoutOptions::Flow;
		setText(pg.text);
	}

	void paint() override
	{
		color col = _select 
			? r::Tabctrl_Header_SelectedColor
			: r::Tabctrl_Header_NormalColor;

		if (enabled)
		{
			if (_press)
				col = col.mulWithoutAlpha(pressFactor);
			else if (_hover)
				col = col.mulWithoutAlpha(hoverFactor);
		}
		Draw::roundedRect(_absPos, _size + vec2{ 0, 10 }, 4, col);

		auto textTex = getTextTexture();
		if (textTex != nullptr)
		{
			color textCol = _select
				? r::Tabctrl_Header_SelectedTextColor
				: r::Tabctrl_Header_NormalTextColor;
			vec2 tsize = textTex->size();
			Draw::text(_absPos + _size / 2.0f - tsize / 2.0f, tsize, *textTex, textCol);
		}
	}

	void flow(ui::Flow& f) override
	{
		//float separator = ui::Theme::current->value("flow.separator");

		auto textTex = getTextTexture();
		vec2 tsize = textTex == nullptr ? vec2{ 0, 0 } : textTex->size();
		tsize = tsize + vec2{ r::Flow_Text_hMargin, r::Flow_Text_vMargin } * 2.0f;
		setSize({
			max(tsize.x, layoutOptions.minSize.x),
			max(tsize.y, layoutOptions.minSize.y) });

		// doesn't care about the line width
		f.lineHeight = max(f.lineHeight, _size.y);
		_parent->setSize({ _parent->size().x, f.currentY + _size.y });
		setPosition({ f.currentX, f.currentY });
		f.currentX += _size.x;
	}
};

ui::TabControl::TabControl(Container* parent, invec2 pos, invec2 size):
	Control(parent, pos, size),
	_header(new Panel((Container*)this)),
	_body(new Panel((Container*)this))
{
	_header->layoutOptions.dock = Control::LayoutOptions::DockType::Top;
	_body->backColor = Colors::magenta;

	_body->layoutOptions.dock = Control::LayoutOptions::DockType::Fill;
}

ui::TabControl::HeaderButton* ui::TabControl::_createButton(Page* p)
{
	auto btn = new HeaderButton(_header, *p);
	btn->onClick = [this, p](auto&)
	{
		select(p);
	};
	return btn;
}

void ui::TabControl::_makeHeader()
{
	ANIP_ui_LoopOverChildrenFrom(_header->firstChild(), child)
	{
		child->markDelete();
	}
	for (unsigned int i = 0; i < _pages.size(); i++)
		_createButton(_pages[i]);
	if (_select >= 0)
	{
		_pages[_select]->_btn->select();
	}
}

ui::TabControl::Page& ui::TabControl::addPage(
	Control& ctrl, const wstring& text, Texture2D* tex)
{
	_body->addChild(ctrl);
	_pages.push_back(new Page(ctrl, text, tex));

	Page* p = _pages.back();
	auto btn = _createButton(p);
	if (_select == -1) 
	{
		_select = 0;
		btn->select();
	}
	return *p;
}

void ui::TabControl::deletePage(Page* page)
{
	auto i = find(_pages.begin(), _pages.end(), page);
	if (i == _pages.end()) throw invalid_argument("page");

	_pages.erase(i);
	page->getContent().markDelete();
	page->_btn->markDelete();
	delete page;
}

void ui::TabControl::detachPage(Page* page)
{
	auto i = find(_pages.begin(), _pages.end(), page);
	if (i == _pages.end()) throw invalid_argument("page");

	_pages.erase(i);
	_body->detachChild(page->getContent());
	page->_btn->markDelete();
	delete page;
}

void ui::TabControl::reorderPage(Page* page, int n)
{
	auto i = find(_pages.begin(), _pages.end(), page);
	if (i == _pages.end()) throw invalid_argument("page");

	auto j = _pages.begin() + n;
	_pages.insert(j, page);
	_pages.erase(i + (j <= i ? 1 : 0));

	if (_select == i - _pages.begin())
		_select = n;

	_makeHeader();
}

void ui::TabControl::select(Page* page)
{
	auto i = find(_pages.begin(), _pages.end(), page);
	if (i == _pages.end()) throw invalid_argument("page");

	_select = i - _pages.begin();
	page->getContent().bringToFront();

	postSignal({ ui::Signal::Type::NeedsReflow });

	_makeHeader();
}

void ui::TabControl::flowChildren(Flow& f)
{
	Flow myFlow((Container&)(*this));
	_header->flow(myFlow);

	bool change = false;
	Control* child = _body->firstChild();
	while (child != nullptr)
	{
		Control* next = child->next();
		if (child->markedDelete())
		{
			change = true;
			for (auto i = _pages.begin(); i != _pages.end(); i++)
				if (&(*i)->getContent() == child)
				{
					_pages.erase(i);
					break;
				}
			_body->detachChild(*child);
			delete child;
		}
		child = next;
	}
	if (change) _makeHeader();

	_body->setPosition({ 0, _header->size().y });
	_body->setSize(_size - vec2{ 0, _header->size().y });
	child = _body->firstChild();
	if (child != nullptr)
	{
		Flow f((Container&)(*this));
		f.dockableStart = { 0, 50 };
		f.dockableEnd = _size;
		child->setPosition({ 0, 0 });
		child->setSize(_body->size());
		child->flow(f);
	}
}

void ui::TabControl::paint()
{
	_header->paint();

	Control* child = _body->firstChild();
	if (child != nullptr)
	{
		Context::setScissor(_body->toAbsolutePos(), _body->size());
		child->paint();
	}
}